package com.yanqu.road.server.manger.player;

import com.alibaba.fastjson.JSON;
import com.yanqu.road.entity.banquet.invitation.BanquetEstateInvitation;
import com.yanqu.road.entity.config.battle.BattleResult;
import com.yanqu.road.entity.config.battle.PatronsBattleDetail;
import com.yanqu.road.entity.config.skin.SkinInfo;
import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.estatewar.*;
import com.yanqu.road.entity.estatewar.palace.PalaceFloorConfig;
import com.yanqu.road.entity.estatewar.palace.UserPalaceData;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.entity.player.UserInfo;
import com.yanqu.road.entity.player.UserPatrons;
import com.yanqu.road.logic.bussiness.player.UserEstateWarBussiness;
import com.yanqu.road.logic.bussiness.player.UserPatronsBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.pb.BattlePb;
import com.yanqu.road.logic.pb.PatronsPb;
import com.yanqu.road.logic.thread.ThreadTaskManger;
import com.yanqu.road.pb.estatewar.EstateWarProto;
import com.yanqu.road.pb.patrons.PatronsProto;
import com.yanqu.road.pb.worldmessage.WorldMessageProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.banquet.BanquetModule;
import com.yanqu.road.server.gameplayer.module.patrons.PatronsModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.gameplayer.module.player.EarnSpeedModule;
import com.yanqu.road.server.gameplayer.module.player.EstateWarModule;
import com.yanqu.road.server.logic.battle.BattleManager;
import com.yanqu.road.server.manger.ConfigMgr;
import com.yanqu.road.server.manger.DataAnalyticsMgr;
import com.yanqu.road.server.manger.config.EstateWarConfigMgr;
import com.yanqu.road.server.manger.config.PatronsMgr;
import com.yanqu.road.server.manger.config.SkinMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.manger.palace.PalaceActivity;
import com.yanqu.road.server.manger.palace.PalaceActivityMgr;
import com.yanqu.road.server.pb.EstateWarPb;
import com.yanqu.road.server.pb.WorldMessagePb;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.UUIDHelper;
import com.yanqu.road.utils.executor.GeneralTask;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 乔迁风云
 */
public class EstateWarMgr extends TempMgr {

    private static Object lockObj = new Object();

    private static Map<Long, UserEstateWarData> userEstateWarDataMap = new ConcurrentHashMap<>();

    private static Map<Integer, Map<Integer, UserEstateFloor>> userEstateFloorMap = new ConcurrentHashMap<>();

    private static Map<Integer, Map<Integer, UserEstateFloor>> npcEstateFloorMap = new ConcurrentHashMap<>();

    private static List<UserEstateFloor> needUpdateUserEstateFloorList = new ArrayList<>();

    private static Map<Integer, EstateWarProto.EstateWarFloorListMsg.Builder> estateWarRankMsgMap = new ConcurrentHashMap<>();

    private static ThreadTaskManger threadTaskManger;

    private static final int MAX_RANK_COUNT = 50;

    private static int canWorshipValue = 0;

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    public boolean save() {
        List<UserEstateFloor> tempList;
        synchronized (needUpdateUserEstateFloorList) {
            tempList = new ArrayList<>(needUpdateUserEstateFloorList);
            needUpdateUserEstateFloorList = new ArrayList<>();
        }
        if (tempList.size() > 0) {
            UserEstateWarBussiness.updateUserEstateFloorList(tempList);
        }
        return true;
    }

    @Override
    public boolean stop() {
        return false;
    }

    @Override
    public boolean reloadData() {
        if(null == threadTaskManger) {
            threadTaskManger = new ThreadTaskManger(1, "estateWarTaskManger");
        }
        userEstateWarDataMap = UserEstateWarBussiness.getUserEstateWarDataMap();
        userEstateFloorMap = UserEstateWarBussiness.getUserEstateFloorMap();
        //初始化机器人楼层
        initNpcEstateFloor();
        //检测并初始化楼层信息
        checkUserEstateFloor();
        //初始化msg
        initEstateWarRankMsg();
        //初始化可膜拜值
        refreshCanWorshipValue();
        return true;
    }

    /**
     * 刷新可膜拜值
     */
    private static void battleRefreshCanWorshipValue() {
        if (refreshCanWorshipValue()) {
            List<GamePlayer> playerList = GamePlayerMgr.getCopyPlayerList();
            for (GamePlayer action : playerList) {
                action.getModule(EstateWarModule.class).syncUserEstateWarData();
            }
        }
    }

    private static Boolean refreshCanWorshipValue() {
        synchronized (lockObj) {
            int oldValue = canWorshipValue;
            int value = 0;
            Map<Integer, EstateBuildingInfo> estateBuildingInfoMap = EstateWarConfigMgr.getEstateBuildingInfoMap();
            for (EstateBuildingInfo estateBuildingInfo : estateBuildingInfoMap.values()) {
                if (EstateWarConfigMgr.getEstateBuildingCanWorship(estateBuildingInfo.getType())) {
                    List<UserEstateFloor> userEstateFloorList = getEstateWarRankFloorList(estateBuildingInfo.getType());
                    if (null != userEstateFloorList && userEstateFloorList.size() > 0) {
                        value = value + (int) Math.pow(2, estateBuildingInfo.getType());
                    }
                }
            }
            canWorshipValue = value;
            return oldValue != value;
        }
    }

    /**
     * 获得可膜拜值
     *
     * @return
     */
    public static int getCanWorshipValue() {
        return canWorshipValue;
    }

    /**
     * 检测公共府邸，并且初始化府邸
     */
    private void checkUserEstateFloor() {
        boolean isChange = false;
        for (Map.Entry<Integer, Map<Integer, EstateFloorInfo>> dataEntry : EstateWarConfigMgr.getEstateFloorInfoMap().entrySet()) {
            if (!EstateWarConfigMgr.getIsNpcEstateBuilding(dataEntry.getKey())) {
                Map<Integer, UserEstateFloor> estateFloorMap = userEstateFloorMap.get(dataEntry.getKey());
                if (null == estateFloorMap) {
                    estateFloorMap = new ConcurrentHashMap<>();
                }
                if (estateFloorMap.size() < dataEntry.getValue().size()) {
                    UserEstateWarBussiness.initUserEstateFloorMap(dataEntry.getValue(), estateFloorMap);
                    isChange = true;
                }
            }
        }
        if (isChange) {
            userEstateFloorMap = UserEstateWarBussiness.getUserEstateFloorMap();
        }
    }

    /**
     * 初始化机器人府邸
     */
    private void initNpcEstateFloor() {
        Map<Integer, Map<Integer, UserEstateFloor>> estateFloorMap = new ConcurrentHashMap<>();
        for (Map.Entry<Integer, Map<Integer, EstateFloorInfo>> dataEntry : EstateWarConfigMgr.getEstateFloorInfoMap().entrySet()) {
            if (EstateWarConfigMgr.getIsNpcEstateBuilding(dataEntry.getKey())) {
                if (!estateFloorMap.containsKey(dataEntry.getKey())) {
                    estateFloorMap.put(dataEntry.getKey(), new ConcurrentHashMap<>());
                }
                for (EstateFloorInfo floorInfo : dataEntry.getValue().values()) {
                    UserEstateFloor userEstateFloor = initUserEstateFloor(floorInfo);
                    estateFloorMap.get(dataEntry.getKey()).put(userEstateFloor.getPos(), userEstateFloor);
                }
            }
        }
        npcEstateFloorMap = estateFloorMap;
    }

    public static void addTask(GeneralTask task) {
        threadTaskManger.addTask(0, task);
    }

    public static UserEstateWarData getUserEstateWarData(long userId) {
        return userEstateWarDataMap.get(userId);
    }

    public static List<UserEstateFloor> getEstateWarRankFloorList(int type) {
        List<UserEstateFloor> estateFloorList = new ArrayList<>();
        Map<Integer, UserEstateFloor> estateFloorMap = getUserEstateFloorMap(type);
        if (null == estateFloorMap) {
            return estateFloorList;
        }
        for (int i = 1; i <= estateFloorMap.size(); i++) {
            UserEstateFloor userEstateFloor = estateFloorMap.get(i);
            if (userEstateFloor.getUserId() > 0) {
                estateFloorList.add(userEstateFloor);
                if (estateFloorList.size() >= MAX_RANK_COUNT) {
                    break;
                }
            }
        }
        return estateFloorList;
    }

    /**
     * 获取可抢占府邸列表
     */
    public static List<UserEstateFloor> getEstateInfo(GamePlayer player) {
        List<UserEstateFloor> estateFloorList = new ArrayList<>();
        UserEstateWarData userEstateWarData = player.getModule(EstateWarModule.class).getUserEstateWarData();
        if (null == userEstateWarData) {
            return estateFloorList;
        }

        UserEstateFloor myFloor = null;
        Map<Integer, UserEstateFloor> estateFloorMap;
        BigInteger totalAbility = player.getModule(PatronsModule.class).getTotalPatronsAbility();
        int floorIndex;
        int myIndex = EstateWarConfigMgr.getEstateFloorIndex(userEstateWarData.getType(), userEstateWarData.getPos());
        int maxIndex = EstateWarConfigMgr.getMaxEstateFloorIndex();
        floorIndex = maxIndex - GameConfig.ESTATE_WAR_MAX_PLAYERS_NUM;
        if (floorIndex > myIndex) {
            floorIndex = myIndex;
            if (EstateWarConfigMgr.getIsNpcEstateBuilding(userEstateWarData.getType())) {
                estateFloorMap = getNpcEstateFloorMap(userEstateWarData.getType());
                if (null != estateFloorMap) {
                    myFloor = estateFloorMap.get(userEstateWarData.getPos());
                    if (null != myFloor) {
                        myFloor = cloneUserEstateFloor(player, myFloor);
                    }
                }
            } else {
                estateFloorMap = getUserEstateFloorMap(userEstateWarData.getType());
                myFloor = estateFloorMap.get(userEstateWarData.getPos());
            }
            if (null != myFloor) {
                estateFloorList.add(myFloor);
            }
        }
        int gapIndex = getGapIndex(totalAbility, myIndex);
        int nextIndex = 0;
        for (int i = 0; i < GameConfig.ESTATE_WAR_MAX_PLAYERS_NUM; i++) {
            nextIndex = nextIndex + gapIndex;
            EstateFloorInfo floorConfig = EstateWarConfigMgr.getEstateFloorInfoByIndex(myIndex + nextIndex);
            if (floorConfig == null) {
                break;
            }
            if (EstateWarConfigMgr.getIsNpcEstateBuilding(floorConfig.getType())) {
                estateFloorMap = getNpcEstateFloorMap(floorConfig.getType());
            } else {
                estateFloorMap = getUserEstateFloorMap(floorConfig.getType());
            }
            UserEstateFloor floor = estateFloorMap.get(floorConfig.getPos());
            estateFloorList.add(floor);
        }
     /*   for (int i = 1; i <= GameConfig.ESTATE_WAR_MAX_PLAYERS_NUM; i++) {
            EstateFloorInfo floorInfo = EstateWarConfigMgr.getEstateFloorInfoByIndex(floorIndex + i);
            if (null == floorInfo) {
                break;
            }
            if (EstateWarConfigMgr.getIsNpcEstateBuilding(floorInfo.getSchoolType())) {
                estateFloorMap = getNpcEstateFloorMap(floorInfo.getSchoolType());
            } else {
                estateFloorMap = getUserEstateFloorMap(floorInfo.getSchoolType());
            }
            estateFloorList.add(estateFloorMap.get(floorInfo.getPos()));
        }*/
        return estateFloorList;
    }

    private static int getGapIndex(BigInteger totalAbility, int myIndex) {
        Map<Integer, UserEstateFloor> estateFloorMap;
        String[] arr = GameConfig.ESTATE_WAR_CHALLENGE_LIST.split(";");
        int gapIndex = 1;
        for (String s : arr) {
            int param = Integer.parseInt(s);
            EstateFloorInfo floorInfo = EstateWarConfigMgr.getEstateFloorInfoByIndex(myIndex + param);
            if (floorInfo == null) {
                continue;
            }
            BigInteger floorTotalAbility;
            if (EstateWarConfigMgr.getIsNpcEstateBuilding(floorInfo.getType())) {
                estateFloorMap = getNpcEstateFloorMap(floorInfo.getType());
                UserEstateFloor estateFloor = estateFloorMap.get(floorInfo.getPos());
                 floorTotalAbility = EstateWarConfigMgr.getNpcAbility(estateFloor.getType(), estateFloor.getPos());
            } else {
                estateFloorMap = getUserEstateFloorMap(floorInfo.getType());
                UserEstateFloor estateFloor = estateFloorMap.get(floorInfo.getPos());
                if (estateFloor.getUserId() == 0) {
                    floorTotalAbility = EstateWarConfigMgr.getNpcAbility(estateFloor.getType(), estateFloor.getPos());
                }else {
                    floorTotalAbility = estateFloor.getTotalAbility();
                }
            }
            if (totalAbility.compareTo(floorTotalAbility) > 0) {
                gapIndex = param / 4;
                break;
            }
        }
        return gapIndex;
    }


    private static int getMaxOfferSet(BigInteger totalAbility, int myIndex) {
        Map<Integer, UserEstateFloor> estateFloorMap;
        String[] arr = GameConfig.ESTATE_WAR_CHALLENGE_LIST.split(";");
        int gapIndex = 1;
        for (String s : arr) {
            int param = Integer.parseInt(s);
            EstateFloorInfo floorInfo = EstateWarConfigMgr.getEstateFloorInfoByIndex(myIndex + param);
            if (floorInfo == null) {
                continue;
            }
            if (EstateWarConfigMgr.getIsNpcEstateBuilding(floorInfo.getType())) {
                estateFloorMap = getNpcEstateFloorMap(floorInfo.getType());
            } else {
                estateFloorMap = getUserEstateFloorMap(floorInfo.getType());
            }
            UserEstateFloor estateFloor = estateFloorMap.get(floorInfo.getPos());
            BigInteger floorTotalAbility = estateFloor.getTotalAbility();
            if (totalAbility.compareTo(floorTotalAbility) > 0) {
                gapIndex = param / 4;
                break;
            }
        }
        int nextIndex = 0;
        for (int i = 0; i < GameConfig.ESTATE_WAR_MAX_PLAYERS_NUM; i++) {
            EstateFloorInfo floorConfig = EstateWarConfigMgr.getEstateFloorInfoByIndex(myIndex + nextIndex + gapIndex);
            nextIndex = nextIndex + gapIndex;
            if (floorConfig == null) {
                break;
            }
        }
        return myIndex + nextIndex;
    }

    /**
     * 复制府邸并设置信息
     */
    private static UserEstateFloor cloneUserEstateFloor(GamePlayer player, UserEstateFloor userEstateFloor) {
        UserEstateFloor cloneFloor = userEstateFloor.clone();
        cloneFloor.setUserId(player.getUserId());
        cloneFloor.setUserBaseInfo(UserMgr.parseUserBaseInfo(player.getUserInfo(), GameServer.getInstance().getServerId()));
        cloneFloor.setTotalAbility(PatronsMgr.getPatronsTotalAbility(player.getUserId()));
        return cloneFloor;
    }

    public static EstateWarProto.EstateWarBattleRespMsg.Builder estateBattle(GamePlayer player, int type, int pos, long enemyServerId, long enemyUserId, int nextType) {
        EstateWarProto.EstateWarBattleRespMsg.Builder msg = EstateWarProto.EstateWarBattleRespMsg.newBuilder();
        UserEstateWarData myEstateWarData = player.getModule(EstateWarModule.class).getUserEstateWarData();
        if (null == myEstateWarData) {
            msg.setRet(GameErrorCode.E_SYSTEM_NO_OPEN);
            return msg;
        }
        BigInteger totalPatronsAbility = player.getModule(PatronsModule.class).getTotalPatronsAbility();
        int myIndex = EstateWarConfigMgr.getEstateFloorIndex(myEstateWarData.getType(), myEstateWarData.getPos());
        if (EstateWarConfigMgr.getIsNpcEstateBuilding(type)) {//私人机器人府邸
            if (EstateWarConfigMgr.isOverCanBattleFloor(type, pos, myEstateWarData.getType(), myEstateWarData.getPos(),getMaxOfferSet(totalPatronsAbility,myIndex))) {//楼层超过范围
                msg.setRet(GameErrorCode.E_ESTATE_WAR_OVER_CAN_ROB_FLOOR);
                return msg;
            }
            return battleNpc(player, type, pos, nextType);
        } else {//公共府邸
            synchronized (lockObj) {
                UserEstateFloor userEstateFloor = getUserEstateFloor(type, pos);
                if (null == userEstateFloor) {
                    msg.setRet(GameErrorCode.E_ESTATE_WAR_FLOOR_NO_FOUND);
                    return msg;
                }
                if (userEstateFloor.getUserBaseInfo().getServerId() != enemyServerId || userEstateFloor.getUserId() != enemyUserId) {//占有人发生变化
                    msg.setRet(GameErrorCode.E_ESTATE_WAR_FLOOR_CHANGE);
                    return msg;
                }
                if (userEstateFloor.getUserBaseInfo().getServerId() == GameServer.getInstance().getServerId() && player.getUserId() == enemyUserId) {
                    msg.setRet(GameErrorCode.E_ESTATE_WAR_CAN_NO_ROB_SELF);
                    return msg;
                }
                myEstateWarData = player.getModule(EstateWarModule.class).getUserEstateWarData();
                if (EstateWarConfigMgr.isOverCanBattleFloor(type, pos, myEstateWarData.getType(), myEstateWarData.getPos(), getMaxOfferSet(totalPatronsAbility, myIndex))) {//楼层超过范围
                    msg.setRet(GameErrorCode.E_ESTATE_WAR_OVER_CAN_ROB_FLOOR);
                    return msg;
                }
                //没人占领，打NPC
                if (userEstateFloor.getUserId() == 0) {
                    return battleNpc(player, type, pos, nextType);
                } else {
                    return battlePlayer(player, type, pos, nextType);
                }
            }
        }
    }

    private static EstateWarProto.EstateWarBattleRespMsg.Builder battleNpc(GamePlayer player, int type, int pos, int nextType) {
        UserEstateWarData userEstateWarData = player.getModule(EstateWarModule.class).getUserEstateWarData();
        EstateWarProto.EstateWarBattleRespMsg.Builder msg = EstateWarProto.EstateWarBattleRespMsg.newBuilder();
        BigInteger totalAbility = player.getModule(PatronsModule.class).getTotalPatronsAbility();
        BigInteger enemyAbility = EstateWarConfigMgr.getNpcAbility(type, pos);
        boolean isWin = false;
        if (totalAbility.compareTo(enemyAbility) >= 0) {
            isWin = true;
        }
        EstateFloorBattleResult battleResult = null;
        if (isWin) {
            //更新占有人
            battleResult = updateEstateFloorUser(player, 0, type, pos);
            if (!EstateWarConfigMgr.getIsNpcEstateBuilding(type)) {//不是机器人建筑
                refreshEstateWarRankMsg(type, pos);
            }
        } else {//失败，触发现金礼包
            player.notifyListener(eGamePlayerEventType.RechargeEstateMoveFloor.getValue(), 0);
            player.notifyListener(eGamePlayerEventType.RechargeEstateMoveFloorNew.getValue(), 0);
        }
        msg.setRet(0);
        msg.setEnemyIsNpc(true);
        msg.setIsWin(isWin);
        msg.setType(type);
        msg.setPos(pos);
        if (null != battleResult) {
            msg.setRiseFloorCount(battleResult.getRiseFloorCount());
            msg.setReward(PropertyHelper.parsePropertyToString(battleResult.getReward()));
        }

        if(isWin){
            touchRecharge(player, type, pos, nextType, totalAbility);
        }

        //乔迁埋点
        DataAnalyticsMgr.trackEstateWarBuyRoom(player, userEstateWarData, 0, type, pos, isWin, totalAbility, enemyAbility);
      return msg;
    }

    private static void touchRecharge(GamePlayer player, int type, int pos, int nextType, BigInteger totalAbility) {
        List<UserEstateFloor> nextList = getEstateInfo(player);
        if(nextList.size() <= 1){
            return;
        }
        nextList.sort(Comparator.comparingInt(UserEstateFloor::getPos));
        UserEstateFloor nextFloor = nextList.get(nextList.size() - 2);
        if(nextFloor.getUserId() == 0) {
            BigInteger newEnemyAbility = EstateWarConfigMgr.getNpcAbility(nextFloor.getType(), nextFloor.getPos());
            if (newEnemyAbility != null && totalAbility.compareTo(newEnemyAbility) < 0) {
                player.notifyListener(eGamePlayerEventType.RechargeEstateMoveFloorNew.getValue(), 0);
            }
        }else{
            long enemyUserId = nextFloor.getUserId();
            List<UserPatrons> myPatronsList = player.getModule(PatronsModule.class).getUserPatronsList();
            GamePlayer enemyPlayer = GamePlayerMgr.getOnlinePlayer(enemyUserId);
            Map<Integer, UserPatrons> enemyPatronsMap;
            if (null != enemyPlayer) {
                enemyPatronsMap = enemyPlayer.getModule(PatronsModule.class).getUserPatronsMap();
            } else {
                enemyPatronsMap = UserPatronsBussiness.getUserPatronsAndSkillMap(nextFloor.getUserId());
            }
            BattleResult result = BattleManager.battle(player.getUserId(), myPatronsList, nextFloor.getUserId(),
                    new ArrayList<>(enemyPatronsMap.values()), 0, false, false);

            boolean win = false;
            if (result.getWinUserId() == player.getUserId()) {
                win = true;
            }
            if(!win){
                player.notifyListener(eGamePlayerEventType.RechargeEstateMoveFloorNew.getValue(), 0);
            }
        }
    }

    public static EstateWarProto.EstateWarBattleRespMsg.Builder battlePlayer(GamePlayer player, int type, int pos, int nextType) {
        UserEstateWarData userEstateWarData = player.getModule(EstateWarModule.class).getUserEstateWarData();
        EstateWarProto.EstateWarBattleRespMsg.Builder msg = EstateWarProto.EstateWarBattleRespMsg.newBuilder();
        UserEstateFloor userEstateFloor = getUserEstateFloor(type, pos);
        long enemyUserId = userEstateFloor.getUserId();
        List<UserPatrons> myPatronsList = player.getModule(PatronsModule.class).getUserPatronsList();
        GamePlayer enemyPlayer = GamePlayerMgr.getOnlinePlayer(enemyUserId);
        Map<Integer, UserPatrons> enemyPatronsMap;
        if (null != enemyPlayer) {
            enemyPatronsMap = enemyPlayer.getModule(PatronsModule.class).getUserPatronsMap();
        } else {
            enemyPatronsMap = UserPatronsBussiness.getUserPatronsAndSkillMap(userEstateFloor.getUserId());
        }
        BattleResult battleResult = BattleManager.battle(player.getUserId(), myPatronsList, userEstateFloor.getUserId(),
                new ArrayList<>(enemyPatronsMap.values()), 0, false, false);

        boolean isWin = false;
        if (battleResult.getWinUserId() == player.getUserId()) {
            isWin = true;
        }

        //增加记录
        addEstateWarRecord(enemyUserId, player.getUserId(), type, pos, isWin);

        EstateFloorBattleResult floorBattleResult = null;
        if (isWin) {//战斗胜利，更新占有人
            floorBattleResult = updateEstateFloorUser(player, enemyUserId, type, pos);
            refreshEstateWarRankMsg(type, pos);
        } else {//失败，触发现金礼包
            player.notifyListener(eGamePlayerEventType.RechargeEstateMoveFloor.getValue(), 0);
            player.notifyListener(eGamePlayerEventType.RechargeEstateMoveFloorNew.getValue(), 0);
        }
        msg.setRet(0);
        msg.setType(type);
        msg.setPos(pos);
        msg.setEnemyIsNpc(false);
        msg.setIsWin(isWin);
        if (null != floorBattleResult) {
            msg.setRiseFloorCount(floorBattleResult.getRiseFloorCount());
            msg.setReward(PropertyHelper.parsePropertyToString(floorBattleResult.getReward()));
        }
        msg.addAllPatronsIdList(battleResult.getMyPatronsIdList());
        //战斗详细信息
        msg.setBattleDetailList(BattlePb.parseBattleDetailListMsg(battleResult.getPatronsBattleDetailList()));
        //对手出战门客、座骑
        for (UserPatrons userPatrons : battleResult.getEnemyPatronsList()) {
            PatronsProto.PatronsTempMsg.Builder patronsMsg = PatronsPb.parsePatronsTempMsg(userPatrons);
            if (null != patronsMsg) {
                msg.addEnemyPatronsList(patronsMsg);
            }
        }
        //乔迁埋点
        BigInteger totalAbility = player.getModule(PatronsModule.class).getTotalPatronsAbility();
        BigInteger enemyAbility = BigInteger.ZERO;
        for (PatronsBattleDetail patronsBattleDetail : battleResult.getPatronsBattleDetailList()) {
            enemyAbility = enemyAbility.add(patronsBattleDetail.getEnemyPatronsTotalBlood());
        }
        DataAnalyticsMgr.trackEstateWarBuyRoom(player, userEstateWarData, enemyUserId, type, pos, isWin, totalAbility, enemyAbility);

        if(isWin){
            touchRecharge(player, type, pos, nextType, totalAbility);
        }
        return msg;
    }

    private static void addEstateWarRecord(long userId, long enemyUserId, int type, int pos, boolean isWin) {
        long nowTime = System.currentTimeMillis() / 1000;
        EstateWarRecord estateWarRecord = new EstateWarRecord();
        estateWarRecord.setRecordUid(UUIDHelper.randomUUID(String.valueOf(GameServer.getInstance().getServerId())));
        estateWarRecord.setWin(isWin);
        estateWarRecord.setUserId(userId);
        estateWarRecord.setRecordTime(nowTime);
        estateWarRecord.setEnemyUserId(enemyUserId);
        UserInfo enemyUserInfo = UserMgr.getUserInfo(enemyUserId);
        estateWarRecord.setEnemyBaseData(UserMgr.parseUserBaseInfo(enemyUserInfo, GameServer.getInstance().getServerId()));
        estateWarRecord.setOldType(type);
        estateWarRecord.setOldPos(pos);
        if (isWin) {
            UserEstateWarData enemyEstateWarData = getUserEstateWarData(enemyUserId);
            estateWarRecord.setNowType(enemyEstateWarData.getType());
            estateWarRecord.setNowPos(enemyEstateWarData.getPos());
        } else {
            estateWarRecord.setNowType(type);
            estateWarRecord.setNowPos(pos);
        }
        estateWarRecord.setInsertOption();
        //添加记录
        GamePlayer player = GamePlayerMgr.getOnlinePlayer(userId);
        if (null != player) {
            player.getModule(EstateWarModule.class).addRecord(estateWarRecord);
            //红点通知
            WorldMessageProto.RedHotNotifyMsg.Builder redHotMsg = WorldMessagePb.parseRedHotNotifyMsg(eRedHotNotifyType.EstateWarBeAttack.getValue(), 1, "");
            player.sendPacket(Protocol.U_RED_HOT_NOTIFY, redHotMsg);
            UserEstateWarData userEstateWarData = player.getModule(EstateWarModule.class).getUserEstateWarData();
            if (null != userEstateWarData) {
                userEstateWarData.setLastBeAttackNotifyTime(nowTime);
            }
        } else {
            UserEstateWarBussiness.addEstateWarRecord(estateWarRecord);
        }
    }

    /**
     * 更新楼层占有人
     */
    private static EstateFloorBattleResult updateEstateFloorUser(GamePlayer player, long enemyUserId, int type, int pos) {
        UserEstateWarData userEstateWarData = player.getModule(EstateWarModule.class).getUserEstateWarData();
        int oldType = userEstateWarData.getType();
        int oldPos = userEstateWarData.getPos();
        UserEstateFloor oldUserEstateFloor = getUserEstateFloor(oldType, oldPos);
        if (!EstateWarConfigMgr.getIsNpcEstateBuilding(type)) {
            UserEstateFloor userEstateFloor = getUserEstateFloor(type, pos);
            long nowTime = System.currentTimeMillis() / 1000;
            if (enemyUserId > 0) {
                //更新楼层信息
                List<UserPatrons> enemyPatronsList = userEstateFloor.getPatronsList();
                updateUserEstateFloor(oldUserEstateFloor, enemyUserId, nowTime, enemyPatronsList);
                //更新用户信息
                updateUserEstateWarData(enemyUserId, oldType, oldPos, true);
                //更新被抢占次数
                UserEstateWarData enemyEstateWarData = getUserEstateWarData(player.getUserId());
                enemyEstateWarData.setTotalBeRobTimes(enemyEstateWarData.getTotalBeRobTimes() + 1);
                //成就、任务
                GamePlayer enemyPlayer = GamePlayerMgr.getOnlinePlayer(enemyUserId);
                if (null != enemyPlayer) {
                    enemyPlayer.getModule(EarnSpeedModule.class).scheduleAddSilver();
                    enemyPlayer.notifyListener(eGamePlayerEventType.EstateWarTotalBeRobTimes.getValue(), enemyEstateWarData);
                } else {
                    UserEstateWarBussiness.updateUserEstateWarData(enemyEstateWarData);
                }
            } else {//清除原楼层状态
                clearEstateFloorUser(oldUserEstateFloor);
            }
            //更新到新楼层
            updateUserEstateFloor(userEstateFloor, player.getUserId(), nowTime, player.getModule(PatronsModule.class).getUserPatronsList());
        }

        //尝试刷新可膜拜值(要在更新楼层玩家数据后)
        if (EstateWarConfigMgr.getEstateBuildingCanWorship(type) && type != oldType) {
            battleRefreshCanWorshipValue();
        }

        //打到固定的楼层生成乔迁帖
        EstateFloorInfo estateFloorInfo = EstateWarConfigMgr.getBanquetInvitationFloor(type, pos, userEstateWarData);
        if (estateFloorInfo != null) {
            BanquetEstateInvitation inv = new BanquetEstateInvitation();
            inv.setType(estateFloorInfo.getType());
            inv.setPos(estateFloorInfo.getPos());
            player.getModule(BanquetModule.class).makeInvitation(eBanquetInvitationType.EstateInvitation.getValue(), JSON.toJSONString(inv));
        }

        //增加楼层奖励
        EstateFloorBattleResult battleResult = EstateWarConfigMgr.getEstateFloorReward(type, pos, userEstateWarData);
        if (null != battleResult && battleResult.getRiseFloorCount() > 0) {//破纪录.
            userEstateWarData.setMaxType(type);
            userEstateWarData.setMaxPos(pos);
            player.getModule(CurrencyModule.class).addCurrency(battleResult.getReward(), eLogMoneyType.EstateWar, eLogMoneyType.EstateWarBattleReward);
            LogMgr.addLogEstateFloorRiseReward(player.getUserId(), battleResult.getRiseFloorCount(), type, pos, PropertyHelper.parsePropertyToString(battleResult.getReward()));
        }

        //更新
        updateUserEstateWarData(player.getUserId(), type, pos, false);
        userEstateWarData.setTotalRobTimes(userEstateWarData.getTotalRobTimes() + 1);
        //成就、任务
        player.notifyListener(eGamePlayerEventType.EstateWarRobTimes.getValue(), 1);
        player.notifyListener(eGamePlayerEventType.EstateWarTotalRobTimes.getValue(), userEstateWarData);
        if (EstateWarConfigMgr.isMaxEstateFloorIndex(type, pos)) {//打上最高层
            WorldMessageMgr.worldNotify(eMessageType.EstateWarRobTopOne.getValue(), player.getUserInfo().getCity(), player.getTitleId(),
                    player.getUserInfo().getNickName(), type, pos);
        }

        return battleResult;
    }

    /**
     * 更新用户信息
     */
    private static void updateUserEstateWarData(long userId, int type, int pos, boolean isBeBattle) {
        UserEstateWarData userEstateWarData = getUserEstateWarData(userId);
        int oldType = userEstateWarData.getType();
        userEstateWarData.setType(type);
        userEstateWarData.setPos(pos);
        // 类型没变化不更改当前皮肤
        if (oldType != type) {
            //更新府邸皮肤
            updateEstateSkin(userId, type, isBeBattle);
        }
        GamePlayer player = GamePlayerMgr.getOnlinePlayer(userId);
        if (null != player) {
            EstateWarModule estateWarModule = player.getModule(EstateWarModule.class);
            //解锁府邸皮肤
            for(int tempType = type; tempType > 0; tempType--){
                int estateSkinId = ConfigMgr.getEstateSkinId(tempType);
                estateWarModule.unlockEstateSkin(estateSkinId);
            }
            //同步
            estateWarModule.syncUserEstateWarData();
            //赚速变化
            estateWarModule.onEstateFloorChange();
            //成就、任务
            player.notifyListener(eGamePlayerEventType.MoveEstateBuilding.getValue(), userEstateWarData);
            player.notifyListener(eGamePlayerEventType.MoveEstateBuildingFloor.getValue(), userEstateWarData);
        } else {
            UserEstateWarBussiness.updateUserEstateWarData(userEstateWarData);
        }
    }

    private static void updateEstateSkin(long userId, int type, boolean isBeBattle){
        UserEstateWarData userEstateWarData = getUserEstateWarData(userId);
        if(isBeBattle) {//被打下来
            SkinInfo skinInfo = SkinMgr.getSkinInfo(userEstateWarData.getEstateSkinId());
            if(null == skinInfo){//皮肤信息出错
                int estateSkinId = ConfigMgr.getEstateSkinId(type);
                if (userEstateWarData.getEstateSkinId() != estateSkinId) {
                    userEstateWarData.setEstateSkinId(estateSkinId);
                }
            }else {//有皮肤信息
                if (skinInfo.getBelongRole() >= 7) {//皇宫皮肤
                    EstateWarMgr.checkEstatePalaceSkin(userEstateWarData);
                }else {//不是皇宫皮肤
                    int estateSkinId = ConfigMgr.getEstateSkinId(type);
                    if (userEstateWarData.getEstateSkinId() != estateSkinId) {
                        userEstateWarData.setEstateSkinId(estateSkinId);
                    }
                }
            }
        }else {//主动打的乔迁
            int estateSkinId = ConfigMgr.getEstateSkinId(type);
            if (userEstateWarData.getEstateSkinId() != estateSkinId) {
                userEstateWarData.setEstateSkinId(estateSkinId);
            }
        }
    }

    private static void updateUserEstateFloor(UserEstateFloor userEstateFloor, long userId, long modifyTime, List<UserPatrons> patronsList) {
        if (null == userEstateFloor) {
            return;
        }
        userEstateFloor.setUserId(userId);
        userEstateFloor.setJoinTime(modifyTime);
        UserInfo userInfo = UserMgr.getUserInfo(userId);
        userEstateFloor.setUserBaseInfo(UserMgr.parseUserBaseInfo(userInfo, GameServer.getInstance().getServerId()));
        if (null != patronsList) {
            userEstateFloor.setTotalAbility(PatronsMgr.getPatronsListAbility(patronsList));
            userEstateFloor.setPatronsList(patronsList);
        }
        if (!needUpdateUserEstateFloorList.contains(userEstateFloor)) {
            needUpdateUserEstateFloorList.add(userEstateFloor);
        }
    }

    public static List<UserPatrons> getEstateFloorPatronsList(long userId) {
        UserEstateWarData userEstateWarData = getUserEstateWarData(userId);
        if (null == userEstateWarData) {
            return null;
        }
        synchronized (lockObj) {
            UserEstateFloor userEstateFloor = getUserEstateFloor(userEstateWarData.getType(), userEstateWarData.getPos());
            if (null == userEstateFloor) {
                return null;
            }
            if (userEstateFloor.getUserId() != userId) {
                return null;
            }
            return new ArrayList<>(userEstateFloor.getPatronsList());
        }
    }

    public static void onUserInfoChange(GamePlayer player, int type, int pos, boolean isUpdateAbility) {
        synchronized (lockObj) {
            UserEstateFloor userEstateFloor = getUserEstateFloor(type, pos);
            if (null == userEstateFloor) {
                return;
            }
            if (userEstateFloor.getUserId() != player.getUserId()) {
                return;
            }
            if (isUpdateAbility) {
                updateUserEstateFloor(userEstateFloor, player.getUserId(), userEstateFloor.getJoinTime(), player.getModule(PatronsModule.class).getUserPatronsList());
            } else {
                updateUserEstateFloor(userEstateFloor, player.getUserId(), userEstateFloor.getJoinTime(), null);
            }
        }
    }

    /**
     * 清除楼层占有状态
     */
    public static void clearEstateFloorUser(UserEstateFloor userEstateFloor) {
        if (null == userEstateFloor) {
            return;
        }
        userEstateFloor.setUserId(0);
        userEstateFloor.setJoinTime(0);
        userEstateFloor.setTotalAbility(BigInteger.ZERO);
        userEstateFloor.setUserBaseInfo(new UserBaseInfo());
        if (!needUpdateUserEstateFloorList.contains(userEstateFloor)) {
            needUpdateUserEstateFloorList.add(userEstateFloor);
        }
    }

    private static void initEstateWarRankMsg() {
        for (Map.Entry<Integer, Map<Integer, UserEstateFloor>> dataEntry : userEstateFloorMap.entrySet()) {
            refreshEstateWarRankMsg(dataEntry.getKey(), 0);
        }
    }

    private static void refreshEstateWarRankMsg(int type, int pos) {
        Map<Integer, UserEstateFloor> estateFloorMap = getUserEstateFloorMap(type);
        if (null == estateFloorMap) {
            return;
        }
        if (pos > 0) {
            EstateWarProto.EstateWarFloorListMsg.Builder rankMsgList = estateWarRankMsgMap.get(type);
            if (rankMsgList.getDataListCount() >= MAX_RANK_COUNT &&
                    pos > rankMsgList.getDataList(rankMsgList.getDataListCount() - 1).getPos()) {//低于榜数不参与排名
                return;
            }
        }
        List<UserEstateFloor> estateFloorList = new ArrayList<>();
        for (int i = 1; i <= estateFloorMap.size(); i++) {
            UserEstateFloor userEstateFloor = estateFloorMap.get(i);
            if (userEstateFloor.getUserId() > 0) {
                estateFloorList.add(userEstateFloor);
                if (estateFloorList.size() >= MAX_RANK_COUNT) {
                    break;
                }
            }
        }
        estateWarRankMsgMap.put(type, EstateWarPb.parseEstateWarFloorListMsg(estateFloorList));
    }

    private static Map<Integer, UserEstateFloor> getUserEstateFloorMap(int type) {
        return userEstateFloorMap.get(type);
    }

    private static Map<Integer, UserEstateFloor> getNpcEstateFloorMap(int type) {
        return npcEstateFloorMap.get(type);
    }

    public static UserEstateFloor getUserEstateFloor(int type, int pos) {
        if (userEstateFloorMap.containsKey(type)) {
            return getUserEstateFloorMap(type).get(pos);
        }
        return null;
    }

    public static void setUserEstateWarData(UserEstateWarData userEstateWarData) {
        if (null != userEstateWarData) {
            userEstateWarDataMap.put(userEstateWarData.getUserId(), userEstateWarData);
        }
    }

    private UserEstateFloor initUserEstateFloor(EstateFloorInfo estateFloorInfo) {
        UserEstateFloor userEstateFloor = new UserEstateFloor();
        userEstateFloor.setType(estateFloorInfo.getType());
        userEstateFloor.setPos(estateFloorInfo.getPos());
        userEstateFloor.setUserId(0);
        userEstateFloor.setUserBaseInfo(new UserBaseInfo());
        userEstateFloor.setTotalAbility(BigInteger.ZERO);
        userEstateFloor.setJoinTime(0);
        return userEstateFloor;
    }

    /**
     * 膜拜
     * @param player
     * @param type
     * @return
     */
    public static EstateWarProto.EstateWarWorshipRespMsg.Builder estateWarWorship(GamePlayer player,int type){
        EstateWarProto.EstateWarWorshipRespMsg.Builder respMsg = EstateWarProto.EstateWarWorshipRespMsg.newBuilder();
        if(!EstateWarConfigMgr.getEstateBuildingCanWorship(type)){
            respMsg.setRet(GameErrorCode.E_ESTATE_WAR_BUILDING_CAN_NO_WORSHIP);
            return respMsg;
        }
        UserEstateWarData userEstateWarData = player.getModule(EstateWarModule.class).getUserEstateWarData();
        if(null == userEstateWarData){
            respMsg.setRet(GameErrorCode.E_SYSTEM_NO_OPEN);
            return respMsg;
        }

        int value = userEstateWarData.getWorshipValue();

        if ((value & ((int) Math.pow(2, type))) == 0) {
            List<UserEstateFloor> userEstateFloorList = EstateWarMgr.getEstateWarRankFloorList(type);
            if(null == userEstateFloorList || userEstateFloorList.size() <= 0) {
                respMsg.setRet(GameErrorCode.E_ESTATE_WAR_WORSHIP_NO_DATA);
                return respMsg;
            }
            EstateWarProto.EstateWarFloorTempMsg.Builder floorDateMsg = EstateWarPb.parseEstateWarFloorTempMsg(userEstateFloorList.get(0));
            userEstateWarData.setWorshipValue(value | ((int) Math.pow(2, type)));
            userEstateWarData.setModifyTime(System.currentTimeMillis() / 1000);
            Property reward = EstateWarConfigMgr.getWorshipReward(userEstateWarData);
            player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.EstateWar, eLogMoneyType.EstateWarWorship);
            player.getModule(EstateWarModule.class).syncUserEstateWarData();
            //成就、任务
            player.notifyListener(eGamePlayerEventType.WorshipTimes.getValue(), 1);
            LogMgr.addLogEstateWorship(player.getUserId(), type, PropertyHelper.parsePropertyToString(reward));

            respMsg.setReward(PropertyHelper.parsePropertyToString(reward));
            if(null != floorDateMsg) {
                respMsg.setUserData(floorDateMsg);
            }
        } else {//膜拜过了
            respMsg.setRet(GameErrorCode.E_ESTATE_WAR_WORSHIP_ALREADY);
            return respMsg;
        }
        respMsg.setRet(0);
        return respMsg;
    }


    public static boolean checkEstatePalaceSkin(UserEstateWarData userEstateWarData){
        if(null == userEstateWarData){
            return false;
        }
        int estateSkinId = userEstateWarData.getEstateSkinId();
        SkinInfo skinInfo = SkinMgr.getSkinInfo(estateSkinId);
        boolean needSetSkin = false;
        if(null == skinInfo){
            needSetSkin = true;
        }else {
            if (skinInfo.getBelongRole() == 7) {//当前装带皇宫皮肤
                PalaceActivity palaceActivity = PalaceActivityMgr.getInTimePalaceActivity();
                if(null == palaceActivity){//没活动了
                    needSetSkin = true;
                }else {
                    int palacePos = 0;
                    UserPalaceData userPalaceData  = palaceActivity.getUserPalaceData(userEstateWarData.getUserId());
                    if(null != userPalaceData){
                        palacePos = userPalaceData.getPos();
                    }
                    int rewardSkinId = 0;
                    PalaceFloorConfig palaceFloorConfig = palaceActivity.getPalaceFloorConfig(palacePos);
                    if(null != palaceFloorConfig){
                        rewardSkinId = palaceFloorConfig.getSkinsReward();
                    }
                    if(rewardSkinId > 0) {
                        SkinInfo rewardSkinInfo = SkinMgr.getSkinInfo(rewardSkinId);
                        if(null == rewardSkinInfo){//找不到对应皇宫皮肤配置
                            needSetSkin = true;
                        }else {
                            if(rewardSkinInfo.getBelongRole() != skinInfo.getBelongRole()){//皇宫皮肤等级不匹配
                                needSetSkin = true;
                            }
                        }
                    }else {//没有皇宫皮肤职位
                        needSetSkin = true;
                    }
                }
            }
        }
        if(needSetSkin){//需要替换皮肤
            int replaceSkinId = ConfigMgr.getEstateSkinId(userEstateWarData.getType());
            userEstateWarData.setEstateSkinId(replaceSkinId);
        }
        return needSetSkin;
    }

    public static Object getLockObj() {
        return lockObj;
    }
}
